#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <malloc.h>
#include <stdlib.h>

#include "interaction.h"
#include "ui_device.h"
#include "login_device.h"
#include "ticket_device.h"
#include "app.h"
#include "log.h"
#include "input_judge.h"
#include "list.h"

static int deal_current_user_point(char *user_id,
                                    struct user **current_user,
                                    struct list_head **current_user_ticket_head,
                                    struct list_head *user_head,
                                    struct list_head *user_ticket_head);
static struct ui_print_ticket_data *link_list_transition(struct list_head *ticket_head);

/**
 * @brief   函数指针控制函数的调用
 * @param   interaction:包含底层数据结构的用来交互的结构体
 *          p_func:指向不同函数的函数指针数组
 * @return  PARAM_ERROR:函数入口参数错误
 *          true:用户点击退出游戏
 */
int control_func(struct interaction *interaction, func_t *p_func)
{
    if (!interaction) {
        DEBUG("PARAM ERROR!");
        return PARAM_ERROR;
    }

    enum ui_options option;

    option = MAIN_MENU;

    while (1) {
        option = p_func[option](interaction);

        if (option == EXIT) {
            return true;
        }
    }
}

/**
 * @brief   用户登录
 * @param   interaction:包含底层数据结构的用来交互的结构体
 * @return  根据用户不同的选择返回不同的宏
 */
int user_login(struct interaction *interaction)
{
    if (!interaction) {
        DEBUG("PARAM ERROR\n");
        return PARAM_ERROR;
    }
	
    struct input_data *ui_return;
    struct ui_print_ticket_data *ticket_data = NULL;
    char user_id[USER_ID_SIZE], passwd[USER_PASSWD_SIZE];
    char *p_return_array;
    int actual_size;
    char string_size;
    int ret = NO_ERROR;

    while (1) {
        /*界面的函数放这里,参数为ret和ui*/
        ui_return = menu_control(&interaction->ui_data[USER_LOGIN],
                                    ticket_data, ret);
        
        ret = NO_ERROR;
        actual_size = 0;
        
        /*检测用户选择了什么选项*/
        if (ui_return->option_type == RETURN) {
            free(ui_return);
            return MAIN_MENU;
        } else if (ui_return->option_type == EXIT) {
            free(ui_return);
            return EXIT;
        }

        /*把不同的值从ui_return->input[100]里面拆分出来*/
        p_return_array = ui_return->input;

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(user_id, p_return_array, actual_size);
        user_id[actual_size] = '\0';

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(passwd, p_return_array, actual_size);
        passwd[actual_size] = '\0';

        /*检测用户输入的数据是否符合要求*/
        if (ui_return->option_type == AFFIRM) {
            /*输入检测*/
            /*账号密码不符合要求，continue这个大循环，重新进入界面函数*/
            if (1 != is_num_or_char(user_id)) {
                ret = ID_ERROR;
                free(ui_return);
                continue;
            } else if (1 != is_num_or_char(passwd)) {
                ret = PASSWD_ERROR;
                free(ui_return);
                continue;
            } else {
                /*匹配数据库中的信息*/
                ret = match_user_info(user_id, passwd,
                                        &interaction->user_head,
                                        interaction->current_user);

                if (ret == ID_NO_MATCH) {
                    free(ui_return);
                    continue;
                }

                /*登录成功*/
                /*把current_user和current_user_ticket_head指向对应的节点*/
                deal_current_user_point(user_id,
                                        &interaction->current_user,
                                        &interaction->current_user_ticket_head,
                                        &interaction->user_head,
                                        &interaction->user_ticket_head);
                free(ui_return);
                return USER_MENU;
            }
        }
    }
    
    free(ui_return);
    return true;
}

/**
 * @brief   用户注册
 * @param   interaction:包含底层数据结构的用来交互的结构体
 * @return  根据用户不同的选择返回不同的宏
 */
int user_register(struct interaction *interaction)
{
    if (!interaction) {
        DEBUG("PARAM ERROR\n");
        return PARAM_ERROR;
    }

    char user_id[USER_ID_SIZE];
    char passwd[USER_PASSWD_SIZE];
    char name[NAME_SIZE];
    char citizen_id[CITIZEN_ID_SIZE];
    char phone_num[PHONE_NUM_SIZE];
    int ret = NO_ERROR;
    int actual_size;
    char string_size;
    char *p_return_array;
    
    struct user *need_add = NULL;
    struct user_ticket *new_user_ticket_list;
    struct input_data *ui_return;
    struct ui_print_ticket_data *ticket_data = NULL;

    while (1) {
        /*界面的函数放这里,参数为ret和ui*/
        ui_return = menu_control(&interaction->ui_data[USER_REGISTER],
                                    ticket_data, ret);

        actual_size = 0;

        /*检测用户选择了什么选项*/
        if (ui_return->option_type == RETURN) {
            free(ui_return);
            return MAIN_MENU;
        } else if (ui_return->option_type == EXIT) {
            free(ui_return);
            return EXIT;
        }

        /*把不同的值从ui_return->input[100]里面拆分出来*/
        p_return_array = ui_return->input;

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(user_id, p_return_array, actual_size);
        user_id[actual_size] = '\0';

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(passwd, p_return_array, actual_size);
        passwd[actual_size] = '\0';

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(name, p_return_array, actual_size);
        name[actual_size] = '\0';

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(citizen_id, p_return_array, actual_size);
        citizen_id[actual_size] = '\0';

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(phone_num, p_return_array, actual_size);
        phone_num[actual_size] = '\0';

        /*检测用户输入的数据是否符合要求*/
        if (ui_return->option_type == AFFIRM) {
            /*输入检测*/
            /*出现错误，continue这个大循环，重新进入界面函数*/
            if (1 != is_num_or_char(user_id)) {
                ret = ID_ERROR;
                free(ui_return);
                continue;
            } else if (1 != is_num_or_char(passwd)) {
                ret = PASSWD_ERROR;
                free(ui_return);
                continue;
            } else if (1 != is_chinese(name)) {
                ret = NAME_ERROR;
                free(ui_return);
                continue;
            } else if (1 != is_num(citizen_id)) {
                ret = CITIZEN_ID_ERROR;
                free(ui_return);
                continue;
            } else if (1 != is_num(phone_num)) {
                ret = PHONE_NUM_ERROR;
                free(ui_return);
                continue;
            } else {
                /*匹配数据库中的信息*/
                /* 判断刚注册的用户名和身份证号是否与他人重复 */
                ret = is_user_info_repeat(user_id, citizen_id,
                                        phone_num,
                                        &interaction->user_head);
            }

            /*注册成功*/
            if (ret != USER_REPEAT) {
                need_add = (struct user *)malloc(sizeof(struct user));

                strncpy(need_add->passwd, passwd, sizeof(passwd));
                strncpy(need_add->user_id, user_id, sizeof(user_id));
                strncpy(need_add->name, name, sizeof(name));
                strncpy(need_add->citizen_id, citizen_id,
                                                sizeof(citizen_id));
                strncpy(need_add->phone_num, phone_num,
                                                sizeof(phone_num));

                list_add_tail(&need_add->list, &interaction->user_head);

                new_user_ticket_list = (struct user_ticket *)malloc(sizeof(struct user_ticket));

                /*初始化新用户的车票的头指针*/
                init_list_head(&new_user_ticket_list->someone_ticket_head);
                list_add_tail(&new_user_ticket_list->list,
                                    &interaction->user_ticket_head);
                free(ui_return);
                ret = REGISTER_SUCCESS;
                continue;
            } else {
                ret = USER_REPEAT;
                free(ui_return);
                continue;
            }
        }
    }

    free(ui_return);
    return false;
}

/**
 * @brief   管理员添加车票
 * @param   interaction:包含底层数据结构的用来交互的结构体
 * @return  根据用户不同的选择返回不同的宏
 */
int add_ticket(struct interaction *interaction)
{
    if (!interaction) {
        DEBUG("PARAM ERROR!\n");
        return PARAM_ERROR;
    }

    struct input_data *ui_return;
    struct ticket *scan_list, *need_check_ticket = NULL;
    struct list_head *pos;
    char origin_place[ORIGIN_PLACE_SIZE], destination[DESTINATION_SIZE],
            departure_time[DEPARTURE_TIME],
            arrival_time[ARRIVAL_TIME],
            train_number[TRAIN_NUM_SIZE], price[PRICE_SIZE],
            ticket_number[TICKET_NUM_SIZE];
    int ret = NO_ERROR;
    char *p_return_array;
    char string_size;
    int actual_size;
    struct ui_print_ticket_data *free_ticket_data_1, *free_ticket_data_2,
                                *ticket_data = NULL;

    while (1) {
        ticket_data = link_list_transition(&interaction->ticket_head);

        ui_return = menu_control(&interaction->ui_data[ADD_TICKET],
                                    ticket_data, ret);
        
        free_ticket_data_2 = free_ticket_data_1 = ticket_data;
        while (free_ticket_data_1) {
            free_ticket_data_1 = free_ticket_data_1->next;
            free(free_ticket_data_2);
            free_ticket_data_2 = free_ticket_data_1;
        }

        actual_size = 0;

        /*检测用户选择了什么选项*/
        if (ui_return->option_type == RETURN) {
            free(ui_return);
            return ADMIN_MENU;
        }

        /*把不同的值从ui_return->input[100]里面拆分出来*/
        p_return_array = ui_return->input;

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(origin_place, p_return_array, actual_size);
        origin_place[actual_size] = '\0';

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(destination, p_return_array, actual_size);
        destination[actual_size] = '\0';

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(departure_time, p_return_array, actual_size);
        departure_time[actual_size] = '\0';

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(arrival_time, p_return_array, actual_size);
        arrival_time[actual_size] = '\0';

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(train_number, p_return_array, actual_size);
        train_number[actual_size] = '\0';

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(price, p_return_array, actual_size);
        price[actual_size] = '\0';

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(ticket_number, p_return_array, actual_size);
        ticket_number[actual_size] = '\0';

        /*检测用户输入的数据是否符合要求*/
        if (ui_return->option_type == AFFIRM) {
            if (1 != is_chinese(origin_place)) {
                ret = ORIGIN_PLACE_NO_STRING;
                free(ui_return);
                continue;
            } else if (1 != is_chinese(destination)) {
                ret = DESTINATION_NO_STRING;
                free(ui_return);
                continue;
            } else if (1 != is_time(departure_time)) {
                ret = DEPARTURE_TIME_FALSE;
                free(ui_return);
                continue;
            } else if (1 != is_time(arrival_time)) {
                ret = ARRIVAL_TIME_FALSE;
                free(ui_return);
                continue;
            } else if (1 != is_num(train_number)) {
                ret = TRAIN_NUM_NO_NUM;
                free(ui_return);
                continue;
            } else if (1 != is_num(price)) {
                ret = PRICE_NO_NUM;
                free(ui_return);
                continue;
            } else if (1 != is_num(ticket_number)) {
                ret = TICKET_NUM_NO_NUM;
                free(ui_return);
                continue;
            }

            need_check_ticket = (struct ticket *)malloc(sizeof(struct ticket));

            strncpy(need_check_ticket->origin_place, origin_place, sizeof(origin_place));
            strncpy(need_check_ticket->destination, destination, sizeof(destination));
            strncpy(need_check_ticket->departure_time, departure_time, sizeof(departure_time));
            strncpy(need_check_ticket->arrival_time, arrival_time, sizeof(arrival_time));
            strncpy(need_check_ticket->train_number, train_number, sizeof(train_number));
            strncpy(need_check_ticket->price, price, sizeof(price));
            strncpy(need_check_ticket->ticket_number, ticket_number, sizeof(ticket_number));

            /*查看车票信息是否重复*/
            /*情形1：信息全部重复，在原来的车票数量上进行叠加*/
            /*情形2：车次重复，其他信息有其中一个不重复，报错*/
            /*情形3：车次不重复，始发站和到达站重复，时间重复，报错*/
            ret = ticket_repeat_check(&interaction->ticket_head,
                                                need_check_ticket);

            /*信息正确，加入链表*/
            if (ret == true) {
                list_add_tail(&need_check_ticket->list, &interaction->ticket_head);
                free(ui_return);
                ret = ADD_SUCCESS;
                continue;
            } else if (ret == TICKET_INFO_REPEAT) {
                list_for_each (pos, &interaction->ticket_head) {
                    scan_list = list_entry(pos, struct ticket, list);
                    if (atoi(scan_list->train_number) == atoi(train_number)) {
                        sprintf(scan_list->ticket_number, "%d", 
                                atoi(scan_list->ticket_number) +
                                atoi(ticket_number));
                        ret = ADD_SUCCESS;
                        break;
                    }
                }
            } else {
                free(ui_return);
                ret = ADD_FALSE;
                continue;
            }

            if (ret == ADD_SUCCESS) {
                free(ui_return);
                continue;
            }
        }
    }

    free(ui_return);
    return false;
}

/**
 * @brief   用户买票
 * @param   interaction:包含底层数据结构的用来交互的结构体
 * @return  根据用户不同的选择返回不同的宏
 */
int buy_ticket(struct interaction *interaction)
{
    if (!interaction) {
        DEBUG("PARAM ERROR!\n");
        return PARAM_ERROR;
    }

    struct input_data *ui_return;
    struct list_head *pos;
    struct ticket *scan_list;
    char train_number[TICKET_NUM_SIZE];
    int ret = NO_ERROR;
    char *p_return_array;
    char string_size;
    int actual_size;
    struct ui_print_ticket_data *free_ticket_data_1, *free_ticket_data_2,
                                *ticket_data = NULL;

    while (1) {
        ticket_data = link_list_transition(&interaction->ticket_head);
        /*界面的函数放这里，参数为ret和ui*/
        ui_return = menu_control(&interaction->ui_data[BUY_TICKET],
                                    ticket_data, ret);

        free_ticket_data_2 = free_ticket_data_1 = ticket_data;
        while (free_ticket_data_1) {
            free_ticket_data_1 = free_ticket_data_1->next;
            free(free_ticket_data_2);
            free_ticket_data_2 = free_ticket_data_1;
        }

        actual_size = 0;

        /*检测用户选择了什么选项*/
        if (ui_return->option_type == RETURN) {
            free(ui_return);
            return USER_MENU;
        }

        /*把不同的值从ui_return->input[100]里面拆分出来*/
        p_return_array = ui_return->input;

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(train_number, p_return_array, actual_size);
        train_number[actual_size] = '\0';

        /*检测用户输入的数据是否符合要求*/
        if (ui_return->option_type == AFFIRM) {
            if (1 != is_num(train_number)) {
                ret = TRAIN_NUM_NO_NUM;
                free(ui_return);
                continue;
            }

            /* 找到用户想要购买的车票 */
            list_for_each (pos, &interaction->ticket_head) {
                scan_list = list_entry(pos, struct ticket, list);
                if (!strcmp(train_number, scan_list->train_number)) {
                    if (atoi(scan_list->ticket_number) > 0) {
                        ret = add_user_ticket(&interaction->current_user_ticket_head,
                                        scan_list);
                        if (ret == true) {
                            ret = BUY_TICKET_SUCCESS;
                            sprintf(scan_list->ticket_number, "%d",
                                    atoi(scan_list->ticket_number) - 1);
                            break;
                        }
                    } else {
                        ret = NO_TICKET_NUM;
                        break;
                    }
                } else {
                    ret = NO_TRAIN_NUM;
                }
            }
            free(ui_return);
            continue;
        }
    }

    free(ui_return);
    return true;
}

/**
 * @brief   管理员登录
 * @param   interaction:包含底层数据结构的用来交互的结构体
 * @return  根据用户不同的选择返回不同的宏
 */
int admin_login(struct interaction *interaction)
{
    if (!interaction) {
        DEBUG("PARAM ERROR!\n");
        return PARAM_ERROR;
    }

    struct input_data *ui_return;
    char admin_id[ADMIN_ID_SIZE], passwd[ADMIN_PASSWD_SIZE];
    int ret = NO_ERROR;
    char *p_return_array;
    char string_size;
    int actual_size;
    struct ui_print_ticket_data *ticket_data = NULL;

    while (1) {
        /*界面的函数放这里，参数为ret和ui*/
        ui_return = menu_control(&interaction->ui_data[ADMIN_LOGIN],
                                    ticket_data, ret);

        actual_size = 0;

        /*检测用户选择了什么选项*/
        if (ui_return->option_type == RETURN) {
            free(ui_return);
            return MAIN_MENU;
        }

        /*把不同的值从ui_return->input里面拆分出来*/
        p_return_array = ui_return->input;

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(admin_id, p_return_array, actual_size);
        admin_id[actual_size] = '\0';

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(passwd, p_return_array, actual_size);
        passwd[actual_size] = '\0';

        /*检测用户输入的数据是否符合要求*/
        if (ui_return->option_type == AFFIRM) {
            if (1 != is_num(admin_id)) {
                ret = ID_ERROR;
                free(ui_return);
                continue;
            } else if (1 != is_num(passwd)) {
                ret = PASSWD_ERROR;
                free(ui_return);
                continue;
            }

            if (!strcmp(admin_id, interaction->admin->admin_id) &&
                !strcmp(passwd, interaction->admin->passwd)) {
                free(ui_return);
                return ADMIN_MENU;
            } else {
                ret = NO_REPEAT;
                free(ui_return);
                continue;
            }
        }
    }

    free(ui_return);
    return true;
}

/**
 * @brief   用户退票
 * @param   interaction:包含底层数据结构的用来交互的结构体
 * @return  根据用户不同的选择返回不同的宏
 */
int return_ticket(struct interaction *interaction)
{
    if (!interaction) {
        DEBUG("PARAM ERROR!\n");
        return PARAM_ERROR;
    }

    struct input_data *ui_return;
    char train_number[TRAIN_NUM_SIZE];
    char *p_return_array;
    char string_size;
    int actual_size;
    int ret = NO_ERROR;
    struct ui_print_ticket_data *free_ticket_data_2, *free_ticket_data_1,
                                    *ticket_data = NULL;

    while (1) {
        ticket_data = link_list_transition(interaction->current_user_ticket_head);

        ui_return = menu_control(&interaction->ui_data[RETURN_TICKET],
                                    ticket_data, ret);

        free_ticket_data_2 = free_ticket_data_1 = ticket_data;
        while (free_ticket_data_1) {
            free_ticket_data_1 = free_ticket_data_1->next;
            free(free_ticket_data_2);
            free_ticket_data_2 = free_ticket_data_1;
        }

        actual_size = 0;

        /*检测用户选择了什么选项*/
        if (ui_return->option_type == RETURN) {
            free(ui_return);
            return USER_MENU;
        }

        /*把不同的值从ui_return->input里面拆分出来*/
        p_return_array = ui_return->input;

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(train_number, p_return_array, actual_size);
        train_number[actual_size] = '\0';

        /*检测用户输入的数据是否符合要求*/
        if (ui_return->option_type == AFFIRM) {
            if (1 != is_num(train_number)) {
                ret = TRAIN_NUM_NO_NUM;
                free(ui_return);
                continue;
            }

            ret = delete_user_ticket(train_number,
                                interaction->current_user_ticket_head);
            if (ret == false) {
                ret = NO_TRAIN_NUM;
                free(ui_return);
                continue;
            } else {
                free(ui_return);
                ret = RETURN_TICKET_SUCCESS;
                continue;
            }
        }
    }

    free(ui_return);
    return true;
}

/**
 * @brief   用户修改个人信息
 * @param   interaction:包含底层数据结构的用来交互的结构体
 * @return  根据用户不同的选择返回不同的宏
 */
int modify_user(struct interaction *interaction)
{
    if (!interaction) {
        DEBUG("PARAM ERROR!\n");
        return PARAM_ERROR;
    }

    struct input_data *ui_return;
    int ret = NO_ERROR;
    int actual_size;
    char *p_return_array;
    char passwd[USER_PASSWD_SIZE];
    char name[NAME_SIZE];
    char citizen_id[CITIZEN_ID_SIZE];
    char phone_num[PHONE_NUM_SIZE];
    char string_size;
    struct ui_print_ticket_data *ticket_data = NULL;

    while (1) {
        ui_return = menu_control(&interaction->ui_data[MODIFY_USER],
                                    ticket_data, ret);

        actual_size = 0;

        if (ui_return->option_type == RETURN) {
            free(ui_return);
            return USER_MENU;
        }

        p_return_array = ui_return->input;

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(passwd, p_return_array, actual_size);
        passwd[actual_size] = '\0';

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(name, p_return_array, actual_size);
        name[actual_size] = '\0';

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(citizen_id, p_return_array, actual_size);
        citizen_id[actual_size] = '\0';

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(phone_num, p_return_array, actual_size);
        phone_num[actual_size] = '\0';

        if (ui_return->option_type == AFFIRM) {
            if (1 != is_num_or_char(passwd)) {
                ret = PASSWD_ERROR;
                free(ui_return);
                continue;
            } else if (1 != is_chinese(name)) {
                ret = NAME_ERROR;
                free(ui_return);
                continue;
            } else if (1 != is_num(citizen_id)) {
                ret = CITIZEN_ID_ERROR;
                free(ui_return);
                continue;
            } else if (1 != is_num(phone_num)) {
                ret = PHONE_NUM_ERROR;
                free(ui_return);
                continue;
            } else {
                /* 判断刚注册的手机号和身份证号是否与他人重复 */
                ret = is_user_info_repeat(",", citizen_id,
                                            phone_num,
                                            &interaction->user_head);
            }

            if (ret == true) {
                strncpy(interaction->current_user->passwd, passwd,
                                                    sizeof(passwd));
                strncpy(interaction->current_user->name, name,
                                                    sizeof(name));
                strncpy(interaction->current_user->citizen_id, citizen_id,
                                                    sizeof(citizen_id));
                strncpy(interaction->current_user->phone_num, phone_num,
                                                    sizeof(phone_num));
                
                free(ui_return);
                ret = MODIFY_SUCCESS;
                continue;
            } else if (ret == USER_REPEAT) {
                free(ui_return);
                continue;
            }
        }
    }

    free(ui_return);
    return false;
}

/**
 * @brief   修改车票信息
 * @param   interaction:包含底层数据结构的用来交互的结构体
 * @return  根据用户不同的选择返回不同的宏
 */
int modify_ticket(struct interaction *interaction)
{
    if (!interaction) {
        DEBUG("PARAM ERROR!\n");
        return PARAM_ERROR;
    }

    struct input_data *ui_return;
    struct ticket *change_ticket, *new_ticket = NULL;
    struct list_head *pos;
    int ret = NO_ERROR;
    int actual_size;
    char *p_return_array;
    char origin_place[ORIGIN_PLACE_SIZE],
            destination[DESTINATION_SIZE],
            departure_time[DEPARTURE_TIME],
            arrival_time[ARRIVAL_TIME],
            train_number[TRAIN_NUM_SIZE], price[PRICE_SIZE],
            ticket_number[TICKET_NUM_SIZE],
            change_train_number[TRAIN_NUM_SIZE];
    char string_size;
    struct ui_print_ticket_data *free_ticket_data_1, *free_ticket_data_2,
                                *ticket_data = NULL;

    while (1) {
        ticket_data = link_list_transition(&interaction->ticket_head);

        ui_return = menu_control(&interaction->ui_data[MODIFY_TICKET],
                                    ticket_data, ret);
        
        free_ticket_data_2 = free_ticket_data_1 = ticket_data;
        while (free_ticket_data_1) {
            free_ticket_data_1 = free_ticket_data_1->next;
            free(free_ticket_data_2);
            free_ticket_data_2 = free_ticket_data_1;
        }

        actual_size = 0;

        if (ui_return->option_type == RETURN) {
            free(ui_return);
            return ADMIN_MENU;
        }

        p_return_array = ui_return->input;

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(change_train_number, p_return_array, actual_size);
        change_train_number[actual_size] = '\0';

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(train_number, p_return_array, actual_size);
        train_number[actual_size] = '\0';

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(origin_place, p_return_array, actual_size);
        origin_place[actual_size] = '\0';

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(destination, p_return_array, actual_size);
        destination[actual_size] = '\0';

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(departure_time, p_return_array, actual_size);
        departure_time[actual_size] = '\0';

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(arrival_time, p_return_array, actual_size);
        arrival_time[actual_size] = '\0';

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(ticket_number, p_return_array, actual_size);
        ticket_number[actual_size] = '\0';

        string_size = p_return_array[actual_size];
        p_return_array = p_return_array + actual_size;
        actual_size = string_size - '0';
        p_return_array = p_return_array + 1;
        strncpy(price, p_return_array, actual_size);
        price[actual_size] = '\0';

        if (ui_return->option_type == AFFIRM) {
            if (1 != is_chinese(origin_place)) {
                ret = ORIGIN_PLACE_NO_STRING;
                free(ui_return);
                continue;
            } else if (1 != is_chinese(destination)) {
                ret = DESTINATION_NO_STRING;
                free(ui_return);
                continue;
            } else if (1 != is_time(departure_time)) {
                ret = DEPARTURE_TIME_FALSE;
                free(ui_return);
                continue;
            } else if (1 != is_time(arrival_time)) {
                ret = ARRIVAL_TIME_FALSE;
                free(ui_return);
                continue;
            } else if (1 != is_num(train_number)) {
                ret = TRAIN_NUM_NO_NUM;
                free(ui_return);
                continue;
            } else if (1 != is_num(price)) {
                ret = PRICE_NO_NUM;
                free(ui_return);
                continue;
            } else if (1 != is_num(ticket_number)) {
                ret = TICKET_NUM_NO_NUM;
                free(ui_return);
                continue;
            } else {
                list_for_each (pos, &interaction->ticket_head) {
                    change_ticket = list_entry(pos, struct ticket,
                                                list);
                    if (!strcmp(change_ticket->train_number,
                                change_train_number)) {
                        new_ticket = (struct ticket *)malloc(sizeof(struct ticket));
                        strncpy(new_ticket->origin_place, origin_place,
                                        sizeof(origin_place));
                        strncpy(new_ticket->destination, destination,
                                        sizeof(destination));
                        strncpy(new_ticket->departure_time, departure_time,
                                        sizeof(departure_time));
                        strncpy(new_ticket->arrival_time, arrival_time,
                                        sizeof(arrival_time));
                        strncpy(new_ticket->train_number, train_number,
                                        sizeof(train_number));
                        strncpy(new_ticket->price, price,
                                        sizeof(price));
                        strncpy(new_ticket->ticket_number, ticket_number,
                                        sizeof(ticket_number));

                        ret = ticket_repeat_check(&interaction->ticket_head,
                                                    new_ticket);
                        free(new_ticket);
                        if (ret == true) {
                            strncpy(change_ticket->origin_place, origin_place,
                                        sizeof(origin_place));
                            strncpy(change_ticket->destination, destination,
                                        sizeof(destination));
                            strncpy(change_ticket->departure_time, departure_time,
                                        sizeof(departure_time));
                            strncpy(change_ticket->arrival_time, arrival_time,
                                        sizeof(arrival_time));
                            strncpy(change_ticket->train_number, train_number,
                                        sizeof(train_number));
                            strncpy(change_ticket->price, price,
                                        sizeof(price));
                            strncpy(change_ticket->ticket_number, ticket_number,
                                        sizeof(ticket_number));

                            break;
                        } else {
                            ret = MODIFY_FALSE;
                            break;
                        }

                    } else {
                        ret = NO_TRAIN_NUM;
                    }
                }

                if (ret == NO_TRAIN_NUM || ret == MODIFY_FALSE) {
                    free(ui_return);
                    continue;
                } else if (ret == true) {
                    free(ui_return);
                    ret = MODIFY_SUCCESS;
                    continue;
                }
            }
        }
    }

    free(ui_return);
    return false;
}


/**
 * @brief   主菜单界面
 * @param   interaction:包含底层数据结构的用来交互的结构体
 * @return  根据用户不同的选择返回不同的宏
 */
int main_menu(struct interaction *interaction)
{
    if (!interaction) {
        DEBUG("PARAM ERROR!\n");
        return PARAM_ERROR;
    }

    struct input_data *ui_return;
    int ret = NO_ERROR;
    struct ui_print_ticket_data *ticket_data = NULL;

    while (1) {
        /*界面的函数放这里,参数为ret和ui*/
        ui_return = menu_control(&interaction->ui_data[MAIN_MENU],
                                    ticket_data, ret);

        /*检测用户选择了什么选项*/
        if (ui_return->option_type == RETURN) {
            free(ui_return);
            return EXIT;
        } else if (ui_return->option_type == USER_LOGIN) {
            free(ui_return);
            return USER_LOGIN;
        } else if (ui_return->option_type == USER_REGISTER) {
            free(ui_return);
            return USER_REGISTER;
        } else if (ui_return->option_type == ADMIN_LOGIN) {
            free(ui_return);
            return ADMIN_LOGIN;
        }
    }

    return false;
}

/**
 * @brief   用户菜单界面
 * @param   interaction:包含底层数据结构的用来交互的结构体
 * @return  根据用户不同的选择返回不同的宏
 */
int user_menu(struct interaction *interaction)
{
    if (!interaction) {
        DEBUG("PARAM ERROR!\n");
        return PARAM_ERROR;
    }

    struct input_data *ui_return;
    int ret = NO_ERROR;
    struct ui_print_ticket_data *ticket_data = NULL;

    while (1) {
        /*界面的函数放这里,参数为ret和ui*/
        ui_return = menu_control(&interaction->ui_data[USER_MENU],
                                    ticket_data, ret);

        /*检测用户选择了什么选项*/
        if (ui_return->option_type == RETURN) {
            free(ui_return);
            return MAIN_MENU;
        } else if (ui_return->option_type == BUY_TICKET_BTN) {
            free(ui_return);
            return BUY_TICKET;
        } else if (ui_return->option_type == RETURN_TICKET_BTN) {
            free(ui_return);
            return RETURN_TICKET;
        } else if (ui_return->option_type == MODIFY_USER_BTN) {
            free(ui_return);
            return MODIFY_USER;
        }
    }

    free(ui_return);
    return false;
}

/**
 * @brief   管理员界面
 * @param   interaction:包含底层数据结构的用来交互的结构体
 * @return  根据用户不同的选择返回不同的宏
 */
int admin_menu(struct interaction *interaction)
{
    if (!interaction) {
        DEBUG("PARAM ERROR!\n");
        return PARAM_ERROR;
    }

    struct input_data *ui_return;
    int ret = NO_ERROR;
    struct ui_print_ticket_data *ticket_data = NULL;

    while (1) {
        /*界面的函数放这里,参数为ret和ui*/
        ui_return = menu_control(&interaction->ui_data[ADMIN_MENU],
                                    ticket_data, ret);

        /*检测用户选择了什么选项*/
        if (ui_return->option_type == RETURN) {
            free(ui_return);
            return MAIN_MENU;
        } else if (ui_return->option_type == ADD_TICKET_BTN) {
            free(ui_return);
            return ADD_TICKET;
        } else if (ui_return->option_type == MODIFY_TICKET_BTN) {
            free(ui_return);
            return MODIFY_TICKET_BTN;
        }
    }

    free(ui_return);
    return true;
}

/**
 * @brief   将current_user和current_user_ticket_head指向对应的节点
 * @param   current_user:指向当前用户信息节点的指针
 *          current_user_ticket_head:指向当前用户的车票信息的指针
 *          user_head:用户信息的头指针
 *          user_ticket_head:用户的车票信息的头指针
 * @return  PARAM_ERROR:入口参数错误
 */
static int deal_current_user_point(char *user_id,
                                    struct user **current_user,
                                    struct list_head **current_user_ticket_head,
                                    struct list_head *user_head,
                                    struct list_head *user_ticket_head)
{
    if (!user_head || !user_ticket_head) {
        DEBUG("PARAM ERROR!\n");
        return PARAM_ERROR;
    }

    int user_count = 0, user_ticket_count = 0;
    struct list_head *pos1, *pos2;
    struct user_ticket *scan_user_ticket_list;
    struct user *scan_user_list;

    list_for_each (pos1, user_head) {
        user_count++;
        scan_user_list = list_entry(pos1, struct user, list);
        if (!strcmp(scan_user_list->user_id, user_id)) {
            *current_user = scan_user_list;
            break;
        }
    }

    list_for_each (pos2, user_ticket_head) {
        user_ticket_count++;
        scan_user_ticket_list = list_entry(pos2, struct user_ticket, list);
        if (user_ticket_count == user_count) {
            *current_user_ticket_head = &scan_user_ticket_list->someone_ticket_head;
        }
    }

    return true;
}

/**
 * @brief   将底层的车票信息结构体赋值给中间层的车票信息结构体
 * @param   ticket_head:包含车票信息的指针
 * @return  NULL:底层车票信息没有数据
 *          data:车票信息的头指针
 */
static struct ui_print_ticket_data *link_list_transition(struct list_head *ticket_head)
{
    struct ui_print_ticket_data *data, *p1, *p2;
    struct list_head *pos;
    struct ticket *message;

    data = p1 = p2 = (struct ui_print_ticket_data *)malloc
                        (sizeof(struct ui_print_ticket_data));

    if (list_empty(ticket_head)) {
        free(data);
        return NULL;
    }
 
    list_for_each (pos, ticket_head) {
        message = list_entry(pos, struct ticket, list);
        p1->train_message[ORIGIN_PLACE_MSG] = message->origin_place;
        p1->train_message[DESTINATION_MSG] = message->destination;
        p1->train_message[TRAIN_NUMBER_MSG] = message->train_number;
        p1->train_message[DEPARTURE_TIME_MSG] = message->departure_time;
        p1->train_message[ARRIVAL_TIME_MSG] = message->arrival_time;
        p1->train_message[PRICE_MSG] = message->price;
        p1->train_message[TICKET_NUMBER_MSG] = message->ticket_number;

        p2->next = p1;
        p2 = p1; 
        p2->next = NULL;

        p1 = (struct ui_print_ticket_data *)malloc
                (sizeof(struct ui_print_ticket_data));
    }

    free(p1);
    return data;
}